package org.javaboy.vhr.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.javaboy.vhr.mapper.SalaryInfoMapper;
import org.javaboy.vhr.model.Employee;
import org.javaboy.vhr.model.Salary;
import org.javaboy.vhr.model.SalaryInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SalaryInfoService {
    private static final Logger logger = LoggerFactory.getLogger(SalaryInfoService.class);
    
    @Autowired
    private SalaryInfoMapper salaryInfoMapper;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private SalaryService salaryService;

    /**
     * 计算应发工资
     * @param salaryInfo 薪资信息
     * @return 应发工资
     */
    private Double calculatePayableSalary(SalaryInfo salaryInfo) {
        return (salaryInfo.getBasicSalary() != null ? salaryInfo.getBasicSalary() : 0.0) +
               (salaryInfo.getPerformanceSalary() != null ? salaryInfo.getPerformanceSalary() : 0.0) +
               (salaryInfo.getOvertimePay() != null ? salaryInfo.getOvertimePay() : 0.0) +
               (salaryInfo.getOthers() != null ? salaryInfo.getOthers() : 0.0) -
               (salaryInfo.getUtilityDeduction() != null ? salaryInfo.getUtilityDeduction() : 0.0);
    }

    /**
     * 计算实发工资
     * @param salaryInfo 薪资信息
     * @return 实发工资
     */
    private Double calculateActualSalary(SalaryInfo salaryInfo) {
        Double payableSalary = calculatePayableSalary(salaryInfo);
        return payableSalary -
               (salaryInfo.getSocialInsuranceDeduction() != null ? salaryInfo.getSocialInsuranceDeduction() : 0.0) -
               (salaryInfo.getHousingFundDeduction() != null ? salaryInfo.getHousingFundDeduction() : 0.0) -
               (salaryInfo.getTax() != null ? salaryInfo.getTax() : 0.0);
    }

    /**
     * 处理薪资计算
     * @param salaryInfo 薪资信息
     */
    private void processSalaryCalculation(SalaryInfo salaryInfo) {
        salaryInfo.setPayableSalary(calculatePayableSalary(salaryInfo));
        salaryInfo.setActualSalary(calculateActualSalary(salaryInfo));
    }

    /**
     * 填充关联信息
     * @param salaryInfo 薪资信息
     */
    private void fillRelatedInfo(SalaryInfo salaryInfo) {
        if (salaryInfo.getEmployeeId() != null) {
            Employee employee = employeeService.getEmployeeById(salaryInfo.getEmployeeId());
            if (employee != null) {
                salaryInfo.setEmployee(employee);
                salaryInfo.setSalaryId(employee.getSalaryId());
                if (employee.getSalaryId() != null) {
                    Salary salary = salaryService.getSalaryById(employee.getSalaryId());
                    salaryInfo.setSalary(salary);
                }
            }
        }
    }

    /**
     * 填充关联信息列表
     * @param salaryInfoList 薪资信息列表
     */
    private void fillRelatedInfoList(List<SalaryInfo> salaryInfoList) {
        salaryInfoList.forEach(this::fillRelatedInfo);
    }

    /**
     * 分页查询工资单信息
     * @param page 当前页码
     * @param size 每页大小
     * @param employeeId 员工ID（可选）
     * @param salaryMonth 工资月份（可选）
     * @param departmentId 部门ID（可选）
     * @param positionId 职位ID（可选）
     * @return 分页查询结果
     */
    public Page<SalaryInfo> getSalaryInfoByPage(Integer page, Integer size, Integer employeeId, String salaryMonth, Integer departmentId, Integer positionId) {
        logger.info("分页查询工资单信息，页码：{}，每页大小：{}，员工ID：{}，工资月份：{}，部门ID：{}，职位ID：{}", 
            page, size, employeeId, salaryMonth, departmentId, positionId);
        
        // 创建分页对象
        Page<SalaryInfo> pageParam = new Page<>(page, size);
        
        // 构建查询条件
        QueryWrapper<SalaryInfo> queryWrapper = new QueryWrapper<>();
        
        // 添加查询条件
        if (employeeId != null) {
            queryWrapper.eq("employee_id", employeeId);
        }
        if (salaryMonth != null && !salaryMonth.isEmpty()) {
            queryWrapper.eq("salary_month", salaryMonth);
        }
        if (departmentId != null) {
            queryWrapper.eq("department_id", departmentId);
        }
        if (positionId != null) {
            queryWrapper.eq("position_id", positionId);
        }
        
        // 添加排序条件
        queryWrapper.orderByDesc("salary_month", "create_time");
        
        try {
            // 执行分页查询
            Page<SalaryInfo> result = salaryInfoMapper.selectPage(pageParam, queryWrapper);
            
            // 填充关联信息
            if (result != null && result.getRecords() != null) {
                fillRelatedInfoList(result.getRecords());
            }
            
            logger.info("分页查询成功，总记录数：{}", result.getTotal());
            return result;
        } catch (Exception e) {
            logger.error("分页查询失败", e);
            throw new RuntimeException("分页查询工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 添加工资单信息
     * @param salaryInfo 工资单信息
     * @return 是否添加成功
     */
    @Transactional
    public boolean addSalaryInfo(SalaryInfo salaryInfo) {
        logger.info("添加工资单信息：{}", salaryInfo);
        try {
            // 填充关联信息
            fillRelatedInfo(salaryInfo);
            
            // 设置时间
            Date now = new Date();
            salaryInfo.setCreateTime(now);
            salaryInfo.setUpdateTime(now);
            
            // 计算工资
            processSalaryCalculation(salaryInfo);
            
            // 执行添加
            int result = salaryInfoMapper.insert(salaryInfo);
            if (result > 0) {
                logger.info("添加工资单信息成功，ID：{}", salaryInfo.getId());
                return true;
            } else {
                logger.warn("添加工资单信息失败");
                return false;
            }
        } catch (Exception e) {
            logger.error("添加工资单信息异常", e);
            throw new RuntimeException("添加工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 更新工资单信息
     * @param salaryInfo 工资单信息
     * @return 是否更新成功
     */
    @Transactional
    public boolean updateSalaryInfo(SalaryInfo salaryInfo) {
        logger.info("更新工资单信息：{}", salaryInfo);
        try {
            // 检查记录是否存在
            SalaryInfo existingInfo = salaryInfoMapper.selectById(salaryInfo.getId());
            if (existingInfo == null) {
                logger.warn("更新失败：工资单信息不存在，ID：{}", salaryInfo.getId());
                return false;
            }
            
            // 填充关联信息
            fillRelatedInfo(salaryInfo);
            
            // 更新时间
            salaryInfo.setUpdateTime(new Date());
            
            // 计算工资
            processSalaryCalculation(salaryInfo);
            
            // 执行更新
            int result = salaryInfoMapper.updateById(salaryInfo);
            if (result > 0) {
                logger.info("更新工资单信息成功，ID：{}", salaryInfo.getId());
                return true;
            } else {
                logger.warn("更新工资单信息失败，ID：{}", salaryInfo.getId());
                return false;
            }
        } catch (Exception e) {
            logger.error("更新工资单信息异常", e);
            throw new RuntimeException("更新工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 删除工资单信息
     * @param id 工资单ID
     * @return 是否删除成功
     */
    @Transactional
    public boolean deleteSalaryInfo(Integer id) {
        logger.info("删除工资单信息，ID：{}", id);
        try {
            // 检查记录是否存在
            SalaryInfo existingInfo = salaryInfoMapper.selectById(id);
            if (existingInfo == null) {
                logger.warn("删除失败：工资单信息不存在，ID：{}", id);
                return false;
            }
            
            // 执行删除
            int result = salaryInfoMapper.deleteById(id);
            if (result > 0) {
                logger.info("删除工资单信息成功，ID：{}", id);
                return true;
            } else {
                logger.warn("删除工资单信息失败，ID：{}", id);
                return false;
            }
        } catch (Exception e) {
            logger.error("删除工资单信息异常", e);
            throw new RuntimeException("删除工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询工资单信息
     * @param id 工资单ID
     * @return 工资单信息
     */
    public SalaryInfo getSalaryInfoById(Integer id) {
        logger.info("查询工资单信息，ID：{}", id);
        try {
            SalaryInfo salaryInfo = salaryInfoMapper.selectById(id);
            if (salaryInfo != null) {
                fillRelatedInfo(salaryInfo);
                logger.info("查询工资单信息成功，ID：{}", id);
                return salaryInfo;
            } else {
                logger.warn("查询失败：工资单信息不存在，ID：{}", id);
                return null;
            }
        } catch (Exception e) {
            logger.error("查询工资单信息异常", e);
            throw new RuntimeException("查询工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 根据员工ID查询工资单信息列表
     * @param employeeId 员工ID
     * @return 工资单信息列表
     */
    public List<SalaryInfo> getSalaryInfoByEmployeeId(Integer employeeId) {
        logger.info("查询员工工资单信息，员工ID：{}", employeeId);
        try {
            QueryWrapper<SalaryInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("employee_id", employeeId)
                       .orderByDesc("salary_month", "create_time");
            
            List<SalaryInfo> salaryInfoList = salaryInfoMapper.selectList(queryWrapper);
            fillRelatedInfoList(salaryInfoList);
            
            logger.info("查询员工工资单信息成功，员工ID：{}，记录数：{}", employeeId, salaryInfoList.size());
            return salaryInfoList;
        } catch (Exception e) {
            logger.error("查询员工工资单信息异常", e);
            throw new RuntimeException("查询员工工资单信息失败：" + e.getMessage());
        }
    }

    /**
     * 查询所有工资单信息
     * @return 工资单信息列表
     */
    public List<SalaryInfo> getAllSalaryInfo() {
        logger.info("查询所有工资单信息");
        try {
            QueryWrapper<SalaryInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.orderByDesc("salary_month", "create_time");
            
            List<SalaryInfo> salaryInfoList = salaryInfoMapper.selectList(queryWrapper);
            fillRelatedInfoList(salaryInfoList);
            
            logger.info("查询所有工资单信息成功，记录数：{}", salaryInfoList.size());
            return salaryInfoList;
        } catch (Exception e) {
            logger.error("查询所有工资单信息异常", e);
            throw new RuntimeException("查询所有工资单信息失败：" + e.getMessage());
        }
    }
} 